﻿using Core.Maths;
using OpenTK.Mathematics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Core.Rendering.Geometry
{
    public class Frustum
    {
        public Plane NearPlane { get; private set; }
        public Plane FarPlane { get; private set; }
        public Plane RightPlane { get; private set; }
        public Plane LeftPlane { get; private set; }
        public Plane TopPlane { get; private set; }
        public Plane BottomPlane { get; private set; }
        public void CalculateFrustum(Camera camera, float aspect, Vector3 position, Quaternion rotation)
        {
            Vector3 front = rotation * Vector3.UnitZ;
            Vector3 right = rotation * Vector3.UnitX;
            Vector3 up = rotation * Vector3.UnitY;
            float halfVside = camera.Far * (float)MathHelper.Tan(MathHelper.DegreesToRadians(camera.Fov / 2));
            float halfHside = halfVside * aspect;
            Vector3 frontMultFar = camera.Far * front;
            NearPlane = new Plane(position + front * camera.Near,front);
            FarPlane = new Plane(position + front * camera.Far, -front);
            RightPlane = new Plane(position, Vector3.Cross(frontMultFar - right * halfHside, up));
            LeftPlane = new Plane(position,Vector3.Cross(frontMultFar + right * halfHside,up));
            TopPlane = new Plane(position, Vector3.Cross(frontMultFar + up * halfVside, right));
            BottomPlane = new Plane(position, Vector3.Cross(frontMultFar - up * halfVside, right));
        }
        private bool IsSphereInFrustum(Sphere sphere)
        {
            return NearPlane.DistanceToPlane(sphere.Position) > -sphere.Radius &&
                FarPlane.DistanceToPlane(sphere.Position) > -sphere.Radius &&
                RightPlane.DistanceToPlane(sphere.Position) > -sphere.Radius &&
                LeftPlane.DistanceToPlane(sphere.Position) > -sphere.Radius &&
                TopPlane.DistanceToPlane(sphere.Position) > -sphere.Radius &&
                BottomPlane.DistanceToPlane(sphere.Position) > -sphere.Radius;
        }
        public bool IsBoundingSphereFrustum(Quaternion rotation,Vector3 scale,Sphere sphere)
        {
            float radius = MathHelper.Max(MathHelper.Max(scale.X, scale.Y), scale.Z) * sphere.Radius;
            Vector3 centerPos = rotation * sphere.Position;
            return IsSphereInFrustum(new Sphere(centerPos, radius));
        }
    }
}
